package hikari.gui.panels;

import com.gooddies.swing.HToggleButton;
import com.gooddies.texteditors.DefaultFloatTextField;
import com.gooddies.wiring.Wiring;
import com.gooddies.wiring.annotations.PostWiring;
import com.gooddies.wiring.annotations.Wire;
import com.gooddies.wiring.annotations.WiringComponent;
import hikari.gui.guicomponents.hLabel;
import hikari.hcomponents.HComponent;
import hikari.hcomponents.RenderEvent;
import hikari.instruments.HikariInstrument;
import hikari.instruments.navmesh.NavmeshAddTriangleInstrument;
import hikari.instruments.navmesh.NavmeshDeletePointInstrument;
import hikari.managers.Manager3D;
import hikari.managers.NavmeshManager;
import hikari.managers.SelectionManager;
import hikari.objects3d.NavMesh3dObject;
import hikari.pathfind.data.CellData;
import hikari.pathfind.data.editor.Cell;
import hikari.pathfind.data.editor.PathFindParams;
import hikari.utils.Utils;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import net.miginfocom.swing.MigLayout;
import org.swig.jirr.IVideoDriver;
import org.swig.jirr.SColor;
import org.swig.jirr.SMaterial;
import org.swig.jirr.vector3df;

/**
 * @author Dmitry
 */
@WiringComponent(singleton = true, lazy = true)
public class NavmeshEditorPanel extends HComponent {

    private final int toggleGroup = "NavmeshEditorWindow".hashCode();
    private HToggleButton removePointsButton;
    private HToggleButton addTrianglesButton;
    private DefaultFloatTextField rectSizeField;
    private HikariInstrument lastInstrument;
    private NavMesh3dObject navmesh;
    private SMaterial inactiveCellMaterial;
    private SMaterial activeCellMaterial;
    private SMaterial connectedCellMaterial;
    private boolean isCellPreview = false;
    @Wire
    private Manager3D manager3D;
    @Wire
    private NavmeshManager navmeshManager;
    @Wire
    private SelectionManager selectionManager;
    @Wire
    private Utils utils;

    private NavmeshEditorPanel() {
    }

    @PostWiring
    private void init() {
        setTitle("Navmesh Settings");
        setLayout(new MigLayout("insets 5"));
        inactiveCellMaterial = new SMaterial();
        inactiveCellMaterial.setEmissiveColor(SColor.WHITE);
        inactiveCellMaterial.setZBuffer((short) 0);
        activeCellMaterial = new SMaterial();
        activeCellMaterial.setZBuffer((short) 0);
        activeCellMaterial.setEmissiveColor(SColor.RED);

        connectedCellMaterial = new SMaterial();
        connectedCellMaterial.setZBuffer((short) 0);
        connectedCellMaterial.setEmissiveColor(SColor.GREEN);

        addTrianglesButton = new HToggleButton(utils.loadImageFromResources("icons/newTriangle.png"));
        addTrianglesButton.setToggleGroup(toggleGroup);
        addTrianglesButton.setClickToDeselect(true);
        addTrianglesButton.setToolTipText("Add Triangles");
        addTrianglesButton.setOnSelect(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                newTriangleSelect();
            }
        });

        addTrianglesButton.setOnDeselect(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                newTriangleDeselect();
            }
        });
        add(addTrianglesButton, "wrap");

        removePointsButton = new HToggleButton(utils.loadImageFromResources("icons/deletePoint.png"));
        removePointsButton.setToggleGroup(toggleGroup);
        removePointsButton.setClickToDeselect(true);
        removePointsButton.setToolTipText("Remove Point");
        removePointsButton.setOnSelect(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                removePointsSelect();
            }
        });

        removePointsButton.setOnDeselect(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                removePointsDeselect();
            }
        });
        add(removePointsButton, "wrap");

        rectSizeField = new DefaultFloatTextField(1, 5000);
        rectSizeField.setValue(PathFindParams.CELL_SIZE);
        add(new hLabel("Rect size"));
        add(rectSizeField, "wrap");

        JButton recalculatePath = new JButton("Recalculate Path");
        recalculatePath.setToolTipText("Bake path");
        recalculatePath.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                recalculatePath();
            }
        });
        add(recalculatePath, "wrap");

        JButton clearPathInfoButton = new JButton("Clear Path Info");
        clearPathInfoButton.setToolTipText("Clear Path Info");
        clearPathInfoButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                clearPathInfo();
            }
        });
        add(clearPathInfoButton, "wrap");

        JButton showCellsButton = new JButton("Show cells");
        showCellsButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                isCellPreview = true;
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                super.mouseReleased(e);
                isCellPreview = false;
            }
        });
        add(showCellsButton, "wrap");
    }

    public NavmeshEditorPanel updateFromModel(NavMesh3dObject object) {
        this.navmesh = object;
        return this;
    }

    private void recalculatePath() {
        PathFindParams.CELL_SIZE = (float) rectSizeField.getValue();
        navmeshManager.clearNavmeshInfo();
        navmeshManager.recalculatePath();
    }

    private void clearPathInfo() {
        navmeshManager.clearNavmeshInfo();
    }

    private void removePointsSelect() {
        lastInstrument = manager3D.getInstrument();
        selectionManager.disableChangeSelection();
        NavmeshDeletePointInstrument instrument = Wiring.getComponent(NavmeshDeletePointInstrument.class);
        instrument.setObject(navmesh);
        manager3D.setInstrument(instrument);
    }

    private void removePointsDeselect() {
        selectionManager.enableChangeSelection();
        manager3D.setInstrument(lastInstrument);
    }

    private void newTriangleSelect() {
        lastInstrument = manager3D.getInstrument();
        selectionManager.disableChangeSelection();
        NavmeshAddTriangleInstrument instrument = Wiring.getComponent(NavmeshAddTriangleInstrument.class);
        instrument.setObject(navmesh);
        manager3D.setInstrument(instrument);
    }

    private void newTriangleDeselect() {
        selectionManager.enableChangeSelection();
        manager3D.setInstrument(lastInstrument);
    }

    @Override
    public RenderEvent registerAfterRenderBeforeGuiEvent() {
        return new RenderEvent() {
            @Override
            public void onRender() {
                if (isCellPreview) {
                    IVideoDriver driver = manager3D.getVideoDriver();
                    drawCells(driver, false, inactiveCellMaterial);
                    drawCells(driver, true, activeCellMaterial);
                    drawConnectedCell(driver, activeCellMaterial);
                }
            }
        };
    }

    private void drawConnectedCell(IVideoDriver driver, SMaterial material) {
        /*vector3df v = new vector3df(0, 0, 0);
         driver.resetTransformMatrix();
         for (CellData cell : NavmeshManager.get().getCells()) {
         cell.getConnection()
         }*/
    }

    private void drawCells(IVideoDriver driver, boolean activity, SMaterial material) {
        vector3df v = new vector3df(0, 0, 0);
        driver.resetTransformMatrix();
        for (CellData cell : navmeshManager.getCells()) {
            float x;
            float y = (float) cell.getY();
            for (int j = 0; j < cell.getyCount(); j++) {
                x = (float) cell.getX();
                for (int i = 0; i < cell.getxCount(); i++) {
                    Cell c = cell.getCell(i, j);
                    if (c.isActive() == activity) {
                        driver.setMaterial(material);
                        v.set(x, 0, y);
                        driver.draw3DAaBbSquare(v, (float) PathFindParams.CELL_SIZE);
                    }

                    x += PathFindParams.CELL_SIZE;
                }

                y += PathFindParams.CELL_SIZE;
            }
        }
    }
}
